package com.yy.job.core.run.flow;

import java.util.Date;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.yy.job.common.dao.po.YYJobDO;
import com.yy.job.common.enums.ErrorCodeEnum;
import com.yy.job.common.enums.JobStatusEnum;
import com.yy.job.core.config.xml.JobXmlConfig;
import com.yy.job.core.config.xml.ModuleXmlConfig;
import com.yy.job.core.domain.JobDomain;
import com.yy.job.core.domain.context.JobContext;
import com.yy.job.spring.YYSpringBeanUtils;
import com.yy.job.utils.ThrowableUtils;
import com.yy.job.utils.exception.YYJobRuntimeException;
import com.yy.job.utils.exception.YYJobRuntimeExceptionUtils;

public class JobRunFlow extends AbsJobRunFlow<JobContext> {

	private static final Logger log = LoggerFactory.getLogger(JobRunFlow.class);

	private ModuleXmlConfig moduleXmlConfig;

	public JobRunFlow(ModuleXmlConfig moduleXmlConfig) {
		this.moduleXmlConfig = moduleXmlConfig;
	}

	@Override
	public void flow(JobContext jobContext) {
		// 幂等判断
		boolean idempotent = this.idempotent(jobContext);
		if(idempotent) {
			return;
		}
		
		try {
			super.flow(jobContext);
		} catch (YYJobRuntimeException e) {
			log.error("jobWorker run YYJobRuntimeException failed ", e);
			this.exception(jobContext, e);
		} catch (Exception e) {
			log.error("jobWorker run Exception failed ", e);
			this.exception(jobContext, e);
		} finally {
			this.end(jobContext);
		}
	}
	
	@Override
	protected boolean idempotent(JobContext jobContext) {
		YYJobDO jobDO = YYSpringBeanUtils.getYYJobDOMapper().selectByPrimaryKey(jobContext.getJobDomain().getId());
		return JobStatusEnum.SUCCESS.getCode().equals(jobDO.getJobStatus()) || JobStatusEnum.CLOSE.getCode().equals(jobDO.getJobStatus());
	}
	
	@Override
	protected void prepare(JobContext jobContext) {
		// 开始执行job
		YYSpringBeanUtils.getJobManager().startJobExecute(jobContext);
	}
	
	/**
	 * 校验job,数据异常直接抛exception,在catch里面处理
	 * 
	 * @param jobContext
	 * @return
	 */
	@Override
	protected void check(JobContext jobContext) {
		JobDomain jobDomain = jobContext.getJobDomain();
		// 数据合法性各种校验
		if (StringUtils.isBlank(jobDomain.getJobCode())) {
			YYJobRuntimeExceptionUtils.throwException(ErrorCodeEnum.CHECK_JOBCODE_NOT_EMPTY);
		}
		JobXmlConfig jobConfig = this.moduleXmlConfig.findByJobCode(jobDomain.getJobCode());
		if (jobConfig == null) {
			YYJobRuntimeExceptionUtils.throwException(ErrorCodeEnum.CHECK_JOBCODE_NOT_ERROR, "jobCode does not exist");
		}
		jobContext.setJobXmlConfig(jobConfig);
	}

	@Override
	public void run(JobContext jobContext) {
		JobStepsRunFlow jobStepsRunFlow = new JobStepsRunFlow();
		jobStepsRunFlow.flow(jobContext);
	}

	@Override
	public void after(JobContext jobContext) {
		jobContext.setExecEndTime(new Date());
	}
	
	@Override
	protected void exception(JobContext jobContext, Exception e) {
		jobContext.setFinalJobStatus(JobStatusEnum.FAIL);
		jobContext.setExecEndTime(new Date());
		
		if(e instanceof YYJobRuntimeException) {
			jobContext.setErrorMsg(((YYJobRuntimeException)e).getMessage());
		} 
		else {
			jobContext.setErrorMsg(e.getMessage());
			jobContext.setErrStack(ThrowableUtils.getStackTrace(e));
		}
	}
	
	@Override
	protected void end(JobContext jobContext) {
		// 结束执行job
		YYSpringBeanUtils.getJobManager().endJobExecute(jobContext);
	}
	
}
